<template>
  <div ref="container" :style="{ width, height }"></div>
</template>

<script setup lang="ts">
import lottie, { type AnimationItem, type AnimationConfig } from 'lottie-web'
import { ref, onMounted, onUnmounted, watch } from 'vue'

interface Props {
  path?: string
  jsonData?: any
  loop?: boolean
  autoplay?: boolean
  speed?: number
  width?: string | number
  height?: string | number
}

const props = withDefaults(defineProps<Props>(), {
  path: '',
  jsonData: null,
  loop: true,
  autoplay: true,
  speed: 1,
  width: '100%',
  height: '100%',
})

const emit = defineEmits<{
  onComplete: []
  onLoopComplete: []
}>()

const container = ref<HTMLElement | null>(null)
let animation: AnimationItem | null = null

const initLottie = async () => {
  if (!container.value) return

  if (animation) {
    animation.destroy()
  }

  const animationData =
    props.jsonData || (props.path ? await fetch(props.path).then((r) => r.json()) : null)

  if (!animationData) return

  const config = {
    container: container.value,
    renderer: 'svg',
    loop: props.loop,
    autoplay: props.autoplay,
    path: props.path,
    animationData: props.jsonData,
  } as AnimationConfig

  animation = lottie.loadAnimation(config)
  animation.setSpeed(props.speed)

  animation.addEventListener('complete', () => emit('onComplete'))
  animation.addEventListener('loopComplete', () => emit('onLoopComplete'))
}

watch(
  () => [props.path, props.jsonData, props.loop, props.speed],
  () => initLottie(),
)

// 控制方法
const play = () => animation?.play()
const pause = () => animation?.pause()
const stop = () => animation?.stop()
const goToAndPlay = (frame: number) => animation?.goToAndPlay(frame, true)
const goToAndStop = (frame: number) => animation?.goToAndStop(frame, true)

defineExpose({
  play,
  pause,
  stop,
  goToAndPlay,
  goToAndStop,
})

onMounted(() => {
  initLottie()
})

onUnmounted(() => {
  if (animation) {
    animation.destroy()
  }
})
</script>
